package com.carpart;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;

import com.carpart.bean.CarPart;
import com.carpart.bean.KeyValue;
import com.carpart.util.LOG;

public class Crawler extends Thread{
	private String year;
	private String postCode;
	private String model;
	private String part;
	private String area;
	private String style;
	private String selPart;
	
	private DataAccess dataAccess = new DataAccess();
	private HttpClient client = new HttpClient();
	private List<NameValuePair> pairs = new ArrayList<NameValuePair>();
	private List<KeyValue> styles = new ArrayList<KeyValue>();
	private List<CarPart> carParts = new ArrayList<CarPart>();
	private int totalPage = 1;
	
	public Crawler(){}
	
	public Crawler(String year, String postCode, String model, String part, String area) {
		this.year = year;
		this.postCode = postCode;
		this.model = model;
		this.part = part;
		this.selPart = part;
		this.area = area;
	}
	
	@Override
	public void run() {
		dataAccess.init(year, model, area, postCode, selPart, "");
		if("all".equals(part)){
			int len = Main.self.partCb.getItemCount();
			for(int i=1; i<len&&Main.self.searchStarted; i++){
				part = ((KeyValue)Main.self.partCb.getItemAt(i)).getKv();
				if(null!=part && part.length()>0){ //循环part
					LOG.info("循环 part (" + (i+1) + "/" + len + ")-> " + part);
					fetch();
				}
			}
		}else{
			LOG.info("提取 part -> " + part);
			fetch();
		}

		List<CarPart> carPartList = dataAccess.query(year, postCode, model, area, selPart, "all");
		Main.self.refreshTable(carPartList);
		List<String> list = dataAccess.queryStyle(year, model, area, postCode, part, "");
		Main.self.refreshStyle(list);
		Main.self.searchComplete();
	}
	
	public void fetch(){
		try{
			pairs.clear();
			styles.clear();
			searchStep1();
			if(styles.size() > 0){
				searchStep2();
			}
		}catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void searchStep1() throws HttpException, IOException{
		PostMethod postMethod = new PostMethod("http://car-part.com/cgi-bin/search.cgi");
//		postMethod.addParameter("userDate", "2008");
//		postMethod.addParameter("userModel", "Toyota Camry");
//		postMethod.addParameter("userPart", "Engine");
//		postMethod.addParameter("userLocation", "California");
//		postMethod.addParameter("userPreference", "year");
//		postMethod.addParameter("userZip", "91765");
		
		postMethod.addParameter("userDate", year);
		postMethod.addParameter("userModel", model);
		postMethod.addParameter("userPart", part);
		postMethod.addParameter("userLocation", area);
		postMethod.addParameter("userPreference", "price");
		postMethod.addParameter("userZip", postCode);
		
		postMethod.addParameter("userVIN", "");
		postMethod.addParameter("svZip", "y");
		postMethod.addParameter("userPage", "1");
		postMethod.addParameter("userInterchange", "None");
		postMethod.addParameter("userDate2", "Ending Year");
		postMethod.addParameter("userSearch", "int");
		
		System.out.println("part -> " + part);
		client.executeMethod(postMethod);
		String result = postMethod.getResponseBodyAsString();
		postMethod.releaseConnection();
		parseStep1(result);
	}
	
	private void parseStep1(String content){
		Matcher styleMatcher = Pattern.compile("<input type='radio' NAME='userInterchange' VALUE='(.*?)'.*?><label.*?>(.*?)</label>").matcher(content);
		Matcher paramMatchet = Pattern.compile("<input type=\"hidden\" NAME=\"(.*?)\" VALUE=\"(.*?)\">").matcher(content);
		
		while(paramMatchet.find()){
			pairs.add(new NameValuePair(paramMatchet.group(1), paramMatchet.group(2)));
		}
		while(styleMatcher.find()){
			styles.add(new KeyValue(styleMatcher.group(1), styleMatcher.group(2)));
		}
		if(styles.size() == 0){
			Matcher matcher = Pattern.compile("<td align=\"center\" height=\"75\"><br><b>(.*?)</b><br /><br />").matcher(content);
			if(matcher.find()){
				LOG.warn("part:" + part + "," + matcher.group(1));
			}else{
				LOG.warn("part:" + part + ",第一步没有查询到数据");
			}
		}
	} 
	
	private void searchStep2() throws HttpException, IOException{
		for(int i=0; i<styles.size()&&Main.self.searchStarted; i++){ //循环style 
			style = styles.get(i).getValue();
			LOG.info("循环 style =>" + style);
			for(int currPage=1; currPage<=totalPage&&Main.self.searchStarted; currPage++){ //循环页码
				PostMethod postMethod = new PostMethod("http://car-part.com/cgi-bin/search.cgi");
				postMethod.addParameters(pairs.toArray(new NameValuePair[pairs.size()]));
				postMethod.addParameter("userInterchange", styles.get(i).getKey());
				postMethod.addParameter("userPage", currPage + "");
				
				System.out.println("style -> " + styles.get(i).getKey());
				client.executeMethod(postMethod);
				String result = postMethod.getResponseBodyAsString();
				postMethod.releaseConnection();
				parseStep2(result);
			}
			dataAccess.insert(carParts);
			carParts.clear();
		}
	}
	
	private void parseStep2(String content){
		Matcher matcher = Pattern.compile("href='.*?userPage=(\\d+?)'").matcher(content);
		while(matcher.find()){
			try{
				int temp = Integer.parseInt(matcher.group(1));
				if(temp > totalPage){
					totalPage = temp;
				}
			}catch (Exception e) {
				e.printStackTrace();
			}
		}
		matcher = Pattern.compile("Dist</a><br>mile</td>([\\s\\S]*?)</table>").matcher(content);
		if(matcher.find()){
			content = matcher.group(1);
			Matcher trMatcher = Pattern.compile("<tr>(.*?)</tr>").matcher(content);
			while(trMatcher.find()){
				String tr = trMatcher.group(1);
				if(tr.indexOf("<td>Year<br>Part<br>Model</td>") != -1){ //最后一行的标题
					break;
				}
				CarPart carPart = new CarPart();
				carPart.setYear(year);
				carPart.setModel(model);
				carPart.setPart(part);
				carPart.setArea(area);
				carPart.setPostcode(postCode);
				carPart.setStyle(style);
				
				Matcher m = Pattern.compile("<td.*?>(.*?)</td><td.*?>(.*?)</td><td.*?>(.*?)</td><td.*?>(.*?)</td><td.*?>(.*?)</td><td.*?>(.*?)</td><td.*?>(.*?)</td><td.*?>(.*?)</td>").matcher(tr);
				Matcher m2 = Pattern.compile("<td.*?>(.*?)</td><td.*?>(.*?)</td><td.*?>(.*?)</td><td.*?>(.*?)</td><td.*?>(.*?)</td><td.*?>(.*?)</td><td.*?>(.*?)</td>").matcher(tr);
				if(m.find()){
					carPart.setYearPartModel(removeSpec(m.group(1)));
					carPart.setDescription(removeSpec(m.group(2)));
//					info.setMiles(removeSpec(m.group(3)));
					carPart.setGrade(removeSpec(m.group(4)));
					carPart.setStock(removeSpec(m.group(5)));
					carPart.setPrice(removeSpec(m.group(6)));
					carPart.setDealer(removeSpec(m.group(7)));
					carPart.setDistMile(removeSpec(m.group(8)));
					carParts.add(carPart);
					
					System.out.println(carPart);
				}else if(m2.find()){
					carPart.setYearPartModel(removeSpec(m2.group(1)));
					carPart.setDescription(removeSpec(m2.group(2)));
					carPart.setGrade(removeSpec(m2.group(3)));
					carPart.setStock(removeSpec(m2.group(4)));
					carPart.setPrice(removeSpec(m2.group(5)));
					carPart.setDealer(removeSpec(m2.group(6)));
					carPart.setDistMile(removeSpec(m2.group(7)));
					carParts.add(carPart);
					
					System.out.println(carPart);
				}
			}
		}
	}
	
	private String removeSpec(String content){
		if(null != content){
			content = content.replaceAll("(<br>)|(&nbsp;)", " ");
			content = content.replaceAll("(<A.*?>)|(<a.*?>)|(</A>)|(</a>)|(<img.*?>)|(</b>)", "");
			return content.trim();
		}
		return "";
	}
	
	public void close(){
		client.getHttpConnectionManager().closeIdleConnections(0);
	}
	
}